package com.huiquan.vocab.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.constant.BaseContants;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.vocab.dao.VocabElementOOaEqualsDao;
import com.huiquan.vocab.dao.VocabElementOOaEqualsDisplayDao;
import com.huiquan.vocab.domain.VocabElementOOaEquals;
import com.huiquan.vocab.domain.VocabElementOOaEqualsDisplay;

@Service
public class VocabElementOOaEqualsService extends BaseService {

	@Autowired
	private VocabElementOOaEqualsDao vocabElementOOaEqualsDao;
	@Autowired
	private VocabElementOOaEqualsDisplayDao vocabElementOOaEqualsDisplayDao;

	public ModelAndView list(String start, String word, String exactSearchFlag, String flag) {

		boolean exactFlag = exactSearchFlag != null && exactSearchFlag.equals("1");
		Map<String, Object> param = new HashMap<>();
		if (word != null && !word.isEmpty()) {
			if (exactFlag) {
				param.put("word", word);
			} else {
				param.put("word", "%" + word + "%");
			}
		}
		if (flag != null && !flag.isEmpty()) {
			param.put("flag", flag);
		}

		int totalSize = vocabElementOOaEqualsDisplayDao.retrieveSize(param);
		Map<String, Integer> page = GetListUtil.getPagingParam(totalSize, start);

		int startIndex = page.get("startIndex");

		// 添加获取列表时需添加的参数
		param.put("orderStr", "o_std desc,oa_std desc");

		List<VocabElementOOaEqualsDisplay> list = new ArrayList<>();
		if (startIndex < totalSize) {
			param.put("startIndex", startIndex);
			list = vocabElementOOaEqualsDisplayDao.retrieveList(param);
		}

		LOGGER.info("Get list success!size = " + list.size());

		Map<String, Object> map = new HashMap<>();
		map.putAll(page);
		map.put("list", list);

		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("word", "词");
		map.put("showSearch", showSearch);

		return new ModelAndView("vocab/element_index", map);
	}

	/**
	 * 对o和oa一致判定数据的初始化：1、判定是否有逻辑冲突；2、对(o和oa一致表)初始化；3、生成列表数据
	 */
	public ReturnData init() throws Exception {
		String msg = "";

		// 查询在判定一致的数据中是否存在错误的词语，如果存在则提示
		List<String> wrongElements = vocabElementOOaEqualsDao.retrieveWrongElement();
		if (wrongElements != null && !wrongElements.isEmpty()) {
			msg += getReturnDataByWrongMsg(wrongElements, "判定相同的数据中有错误元素，请核对：");
		}

		// 不能有两组o同义词组的元素指向同一个oa同义词组
		List<String> wrongSynonyms = vocabElementOOaEqualsDao.retrieveWrongSynonyms();
		if (wrongSynonyms != null && !wrongSynonyms.isEmpty()) {
			msg += getReturnDataByWrongMsg(wrongSynonyms, "有两组o同义词组的元素指向同一个oa同义词组：");
		}

		// 初始化前有问题，则不初始化先提示
		if (!msg.isEmpty()) {
			ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
			rc.setDesc(msg);
			return ReturnUtil.fail(rc);
		}

		// 对(o和oa一致表)初始化
		initOOaEquals();

		// 生成列表数据
		initDisplay();

		// 如果生成好的数据存在同一组o等价于两组oa同义词，则提示
		List<String> wrongEquals = vocabElementOOaEqualsDisplayDao.retrieveWrongEquals();
		if (wrongEquals != null && !wrongEquals.isEmpty()) {
			msg += getReturnDataByWrongMsg(wrongEquals, "同一组o等价于两组oa同义词：");
		}

		// 如果一组同义词中不同元素有不同答案，则提示
		List<String> wrongFlags = vocabElementOOaEqualsDisplayDao.retrieveWrongFlags();
		if (wrongFlags != null && !wrongFlags.isEmpty()) {
			msg += getReturnDataByWrongMsg(wrongFlags, "一组同义词中不同元素有不同答案：");
		}

		// 初始化后有问题，则提示
		if (!msg.isEmpty()) {
			ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
			rc.setDesc(msg);
			return ReturnUtil.fail(rc);
		}

		return ReturnUtil.success();
	}

	/**
	 * 根据一致表中同义词合并，初始化展现数据
	 */
	private void initDisplay() {
		
		// 先重置表
		vocabElementOOaEqualsDisplayDao.reset();

		List<VocabElementOOaEquals> subs = vocabElementOOaEqualsDao.retrieveList();
		String oStd = null, oaStd = null;
		List<VocabElementOOaEqualsDisplay> groups = new ArrayList<>();
		VocabElementOOaEqualsDisplay display = new VocabElementOOaEqualsDisplay();

		for (VocabElementOOaEquals sub : subs) {
			// 根据oStd和oaStd两个字段来分组，如果其中有一个空值则该词独立一组
			boolean synonymFlag = sub.getoStd().equals(oStd) && sub.getOaStd().equals(oaStd);
			boolean notEmptyFlag = !sub.getoStd().isEmpty() && !sub.getOaStd().isEmpty();
			if (synonymFlag && notEmptyFlag) {
				// 两个同义词都和上一条数据相同，并且两个同义词都不是空值
				display.setWords(display.getWords() + "," + sub.getWord());
				display.setFlags(display.getFlags() + "," + sub.getFlag());
			} else {
				oStd = sub.getoStd();
				oaStd = sub.getOaStd();

				// 其他情况都需要重新添加数据
				display = new VocabElementOOaEqualsDisplay();
				display.setoStd(sub.getoStd());
				display.setOaStd(sub.getOaStd());
				display.setFlag(sub.getFlag());
				display.setWords(sub.getWord());
				display.setFlags(sub.getFlag().toString());
				groups.add(display);
			}
		}

		vocabElementOOaEqualsDisplayDao.batchInsert(groups);
	}

	/**
	 * 根据错误的词语获取返回信息
	 * 
	 * @param wrongElements
	 * @return
	 */
	private String getReturnDataByWrongMsg(List<String> wrongElements, String msgPre) {

		StringBuffer msg = new StringBuffer(msgPre);
		for (String wrongElement : wrongElements) {
			msg.append(wrongElement);
			msg.append("；");
		}
		msg.append("\n");

		ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
		rc.setDesc(msg.toString());

		return msg.toString();
	}

	/**
	 * 对(o和oa一致表)初始化
	 */
	private void initOOaEquals() {
		// 先将未校验的数据删除，然后更新已校验的数据的词语id和标准词，根据o和oa词语相同的数据添加数据，自动校验部分未校验数据
		vocabElementOOaEqualsDao.init();
	}

	/**
	 * 一页提交时，需要更改展现表数据和明细表中的flag
	 * 
	 * @param checkedIds
	 * @param unCheckedIds
	 * @return
	 */
	public ReturnData checkPage(String checkedIds, String unCheckedIds) {

		// 先维护展现表数据：更改两个正误字段
		String displayIds = "0";
		if(checkedIds!=null && !checkedIds.isEmpty()) {
			vocabElementOOaEqualsDisplayDao.setFlagByIds(checkedIds, BaseContants.FLAG_YES);
			displayIds += "," + checkedIds;
		}
		if(unCheckedIds!=null && !unCheckedIds.isEmpty()) {
			vocabElementOOaEqualsDisplayDao.setFlagByIds(unCheckedIds, BaseContants.FLAG_NO);
			displayIds += "," + unCheckedIds;
		}

		// 再维护各个分词
		vocabElementOOaEqualsDao.setFlagByDisplay(displayIds);

		return ReturnUtil.success();
	}
}
